package cn.com.libertymutual.core.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.beanutils.converters.SqlDateConverter;
import org.apache.commons.beanutils.converters.SqlTimestampConverter;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 对象复制工具类
 * 
 * 处理 Date为空的BUG
 */

public class BeanUtilExt extends BeanUtils {
	private static Logger logger = LoggerFactory.getLogger(BeanUtilExt.class);

	private BeanUtilExt() {

	}

	static {
		// 注册sql.date的转换器，即允许BeanUtils.copyProperties时的源目标的sql类型的值允许为空
		ConvertUtils.register(new SqlDateConverter(null), java.util.Date.class);
		ConvertUtils.register(new SqlTimestampConverter(null), java.sql.Timestamp.class);
		// 注册util.date的转换器，即允许BeanUtils.copyProperties时的源目标的util类型的值允许为空
		ConvertUtils.register(new DateConverter(null), java.util.Date.class);
	}

	public static void copyProperties(Object target, Object source) throws InvocationTargetException, IllegalAccessException {
		// 支持对日期copy
		org.apache.commons.beanutils.BeanUtils.copyProperties(target, source);

	}

	/**
	 * Remarks: 将class1对象的属性值映射到class2中，只映射class2属性值=====【为空的】=====属性<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月22日下午6:59:09<br>
	 * Project：liberty_sale_plat<br>
	 * 
	 * @param class1
	 * @param class2
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static void reflectAbeanToBbean(Object class1, Object class2)
			throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		// 获取实体类的所有属性，返回Field数组
		Field[] field1 = class1.getClass().getDeclaredFields();
		Field[] field2 = class2.getClass().getDeclaredFields();
		for (int i = 0; i < field1.length; i++) {
			// 获取属性的名字
			String name = field1[i].getName();
			if (name.toUpperCase().equals("serialVersionUID".toUpperCase())) {
				continue;
			}
			// 将属性的首字符大写，方便构造get，set方法
			name = name.substring(0, 1).toUpperCase() + name.substring(1);
			Method m1 = class1.getClass().getMethod("get" + name);
			// 调用getter方法获取属性值
			Object value = m1.invoke(class1);
			if (value != null) {
				Field f = field2[i];
				f.setAccessible(true); // 设置些属性是可以访问的
				Object val = f.get(class2);// 得到class2的此属性的值
				if (val == null) {
					f.set(class2, value); // 给属性设值
				}
			}
		}
	}

	/**
	 * Remarks: 将class1对象的属性值映射到class2中，只映射class2属性值=====【不相等的】=====属性<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月22日下午6:59:09<br>
	 * Project：liberty_sale_plat<br>
	 * 
	 * @param class1
	 * @param class2
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static void copybean1ToBbean2(Object class1, Object class2)
			throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

		// logger.info("=====================================原：" +
		// JSON.toJSONString(class1));
		// 获取实体类的所有属性，返回Field数组
		Field[] field1 = class1.getClass().getDeclaredFields();
		Field[] field2 = class2.getClass().getDeclaredFields();
		for (int i = 0; i < field1.length; i++) {
			// 获取属性的名字
			String name = field1[i].getName();
			if (name.toUpperCase().equals("serialVersionUID".toUpperCase())) {
				continue;
			}
			// 将属性的首字符大写，方便构造get，set方法
			name = name.substring(0, 1).toUpperCase() + name.substring(1);
			Method m1 = class1.getClass().getMethod("get" + name);
			// 调用getter方法获取属性值
			Object value = m1.invoke(class1);
			if (value != null) {
				Field f = field2[i];
				f.setAccessible(true); // 设置些属性是可以访问的
				Object val = f.get(class2);// 得到class2的此属性的值
				if (val != value) {
					f.set(class2, value); // 给属性设值
				}
			}
		}

		// logger.info("=====================================新：" +
		// JSON.toJSONString(class2));
	}

	/**
	 * Remarks: 将class2对象的属性值映射到class1中<br>
	 * Version：1.0<br>
	 * Author：LJ<br>
	 * DateTime：2017年11月22日下午6:59:09<br>
	 * Project：liberty_sale_plat<br>
	 * 
	 * @param class1
	 * @param class2
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static Object differAbeanToBbean(Object class1, Object class2)
			throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		// 获取实体类的所有属性，返回Field数组
		Field[] field1 = class1.getClass().getDeclaredFields();
		Field[] field2 = class2.getClass().getDeclaredFields();
		for (int i = 0; i < field1.length; i++) {
			// 获取属性的名字
			String name = field1[i].getName();
			if (name.toUpperCase().equals("serialVersionUID".toUpperCase())) {
				continue;
			}
			// 将属性的首字符大写，方便构造get，set方法
			name = name.substring(0, 1).toUpperCase() + name.substring(1);
			Method m1 = class1.getClass().getMethod("get" + name);
			// 调用getter方法获取属性值
			Object value = m1.invoke(class1);
			Field f = field2[i];
			f.setAccessible(true); // 设置些属性是可以访问的
			Object val = f.get(class2);// 得到class2的此属性的值
			if (val != value) {
				field1[i].setAccessible(true);
				field1[i].set(class1, val); // 给属性设值
			}
		}
		return class1;
	}

	/**
	 * 实体转化copy 方法
	 * 
	 * @update 添加使用 ObjectMapper 转化的方法.使 @JsonProperty 可用
	 * @param target
	 * @param source
	 * @return
	 */
	public static <T> T copy(Class<T> target, Object source) {
		ObjectMapper mapper = new ObjectMapper();
		// 设置转换时,如果有多余的参数,不报错.忽略多余的参数
		mapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		try {
			logger.debug("copy from " + source.toString());
			T t = null;
			if (source instanceof String) {
				t = mapper.readValue(source.toString(), target);
			} else {
				String tx = mapper.writeValueAsString(source);
				logger.debug("copy to json  >> " + tx);
				t = mapper.readValue(tx, target);
			}

			return t;
		} catch (Exception e) {
			logger.error("ERROR: can't copy by ObjectMapper.readValue " + e.getMessage());
			return null;
		}
	}

	public static String toJsonString(Object o) {
		if (o == null)
			return null;
		ObjectMapper mapper = new ObjectMapper();
		// 设置转换时,如果有多余的参数,不报错.忽略多余的参数
		mapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

		// 通过该方法对mapper对象进行设置，所有序列化的对象都将按改规则进行系列化
		// Include.Include.ALWAYS 默认
		// Include.NON_DEFAULT 属性为默认值不序列化
		// Include.NON_EMPTY 属性为 空（“”） 或者为 NULL 都不序列化
		// Include.NON_NULL 属性为NULL 不序列化
		mapper.setSerializationInclusion(Include.NON_NULL);
		String tx;
		try {
			tx = mapper.writeValueAsString(o);
		} catch (JsonProcessingException e) {
			logger.error(e.getMessage(), e);
			tx = JSON.toJSONString(o);
		}
		return tx;
	}

	public static void main(String[] args) {
		// String as =
		// "{\"resultMessage\":\"成功\",\"flowId\":\"LBS00230173451\",\"machineCode\":\"05-03-20150303-0003040171\"}";
	}

}
